package com.dayu.recovery.service.impl;

import java.math.BigDecimal;
import java.util.*;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dayu.common.annotation.DataScope;
import com.dayu.common.core.domain.entity.SysUser;
import com.dayu.common.utils.DateUtils;
import com.dayu.common.utils.SecurityUtils;
import com.dayu.recovery.domain.RecoveryData;
import com.dayu.recovery.domain.RecoveryGoods;
import com.dayu.recovery.domain.RecoveryParts;
import com.dayu.recovery.domain.export.BillAndCollectExport;
import com.dayu.recovery.mapper.RecoveryGoodsMapper;
import com.dayu.recovery.service.IRecoveryPartsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.dayu.recovery.mapper.RecoveryBillMapper;
import com.dayu.recovery.domain.RecoveryBill;
import com.dayu.recovery.service.IRecoveryBillService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

/**
 * 财务账单Service业务层处理
 * 
 * @author HK
 * @date 2021-04-16
 */
@Service
public class RecoveryBillServiceImpl implements IRecoveryBillService
{
    @Autowired
    private RecoveryBillMapper recoveryBillMapper;
    @Autowired
    private RecoveryGoodsMapper recoveryGoodsMapper;
    @Autowired
    private IRecoveryPartsService partsService;
    /**
     * 查询财务账单
     * 
     * @param billId 财务账单ID
     * @return 财务账单
     */
    @Override
    public RecoveryBill selectRecoveryBillById(Long billId)
    {
        return recoveryBillMapper.selectRecoveryBillById(billId);
    }

    @DataScope(deptAlias = "d", userAlias = "u")
    @Override
    public List<RecoveryBill> selectRecoveryBillBySellList(RecoveryBill recoveryBill) {
        return recoveryBillMapper.selectRecoveryBillBySellList(recoveryBill);
    }

    /**
     * 查询财务账单列表
     * 
     * @param recoveryBill 财务账单
     * @return 财务账单
     */
    @DataScope(deptAlias = "d", userAlias = "u")
    @Override
    public List<RecoveryBill> selectRecoveryBillList(RecoveryBill recoveryBill)
    {
        return recoveryBillMapper.selectRecoveryBillList(recoveryBill);
    }

    @Override
    public List<BillAndCollectExport> selectRecoveryBillListExport(RecoveryBill recoveryBill) {
        return recoveryBillMapper.selectRecoveryBillListExport(recoveryBill);
    }

    /**
     * 新增财务账单
     * 
     * @param recoveryBill 财务账单
     * @return 结果
     */
    @Override
    public int insertRecoveryBill(RecoveryBill recoveryBill)
    {
//        recoveryBill.setSellBy(SecurityUtils.getLoginUser().getUser().getNickName());
        recoveryBill.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        recoveryBill.setProfit(recoveryBill.getSellPrice().subtract(recoveryBill.getCostPrice()));
        recoveryBill.setCreateId(SecurityUtils.getLoginUser().getUser().getUserId());
        recoveryBill.setCreateTime(DateUtils.getNowDate());
        return recoveryBillMapper.insertRecoveryBill(recoveryBill);
    }

    /**
     * 修改财务账单
     * 
     * @param recoveryBill 财务账单
     * @return 结果
     */
    @Override
    public int updateRecoveryBill(RecoveryBill recoveryBill)
    {
        if(recoveryBill.getSellPrice() != null && recoveryBill.getCostPrice() != null) {
            recoveryBill.setProfit(recoveryBill.getSellPrice().subtract(recoveryBill.getCostPrice()));
            //减去配送费
            if(!ObjectUtils.isEmpty(recoveryBill.getGivePrice())) {
                recoveryBill.setProfit(recoveryBill.getProfit().subtract(recoveryBill.getGivePrice()));
            }
            //利润减去配件成本
            if(!ObjectUtils.isEmpty(recoveryBill.getPartsPrice())) {
                recoveryBill.setProfit(recoveryBill.getProfit().subtract(recoveryBill.getPartsPrice()));
            }
        }
        recoveryBill.setUpdateId(SecurityUtils.getLoginUser().getUser().getUserId());
        recoveryBill.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        recoveryBill.setUpdateTime(DateUtils.getNowDate());
        return recoveryBillMapper.updateRecoveryBill(recoveryBill);
    }

    /**
     * 批量删除财务账单
     * 
     * @param billIds 需要删除的财务账单ID
     * @return 结果
     */
    @Override
    public int deleteRecoveryBillByIds(Long[] billIds)
    {
        return recoveryBillMapper.deleteRecoveryBillByIds(billIds);
    }

    /**
     * 删除财务账单信息
     * 
     * @param billId 财务账单ID
     * @return 结果
     */
    @Override
    public int deleteRecoveryBillById(Long billId)
    {
        return recoveryBillMapper.deleteRecoveryBillById(billId);
    }

    /**
     * 批量出售
     * @param list
     * @return
     */
    @Override
    @Transactional
    public int sellGoodsByList(List<RecoveryBill> list) {
        List<RecoveryGoods> goodsList = new ArrayList<>();
        Date date = new Date();
        SysUser user = SecurityUtils.getLoginUser().getUser();
        List<String> partsIds = new ArrayList<>();
        for(RecoveryBill bill : list) {
            //配件id组，用于配件减库
            partsIds.add(bill.getPartsIds());

            RecoveryGoods goods = new RecoveryGoods();
            goods.setGoodsId(bill.getGoodsId());
            goodsList.add(goods);
            bill.setCreateTime(date);
            bill.setCreateBy(user.getNickName());
            bill.setCreateId(user.getUserId());
            BigDecimal b = new BigDecimal(0);

            //售价
            if(!ObjectUtils.isEmpty(bill.getSellPrice())) {
                 b = b.add(bill.getSellPrice());
            }
            //商品成本
            if(!ObjectUtils.isEmpty(bill.getCostPrice())) {
                b = b.subtract(bill.getCostPrice());
            }
            //配送费
            if(!ObjectUtils.isEmpty(bill.getGivePrice())) {
                b = b.subtract(bill.getGivePrice());
            }
            //配件成本
            if(!ObjectUtils.isEmpty(bill.getPartsPrice())) {
               b = b.subtract(bill.getPartsPrice());
            }
            bill.setProfit(b);
        }

        //减库存操作
        subtractPartsNo(partsIds);

        return recoveryBillMapper.insertBillByList(list);
    }

    private void subtractPartsNo(List<String> list) {
        Map<String, Integer> map = new HashMap<>();
        for (String s : list) {
            if(ObjectUtils.isEmpty(s)) {
                continue;
            }
            String[] a = s.split(",");
            for(String i : a) {
                if(map.get(i) == null) {
                    map.put(i, 1);
                }else {
                    int b = map.get(i) + 1;
                    map.put(i, b);
                }
            }
        }
        for(String key : map.keySet()) {
            RecoveryParts parts = partsService.selectRecoveryPartsById(Long.parseLong(key));
            parts.setPartsNo( parts.getPartsNo() - map.get(key));
            partsService.updateRecoveryParts(parts);
        }
    }

    private String[] getGoodsIds(List<RecoveryGoods> goodsList) {
        String[] arr = new String[goodsList.size()];
        for(int i = 0; i < goodsList.size(); i++) {
            arr[i] = goodsList.get(i).getGoodsId();
        }
        return arr;
    }

    /**
     * 退单处理
     * @param recoveryBill 前端传入数据
     * @return 执行成功条数
     */
    @Override
    @Transactional
    public int returnGoodsByBill(RecoveryBill recoveryBill) {
        RecoveryBill oldBill = recoveryBillMapper.selectRecoveryBillById(recoveryBill.getBillId());
        oldBill.setStatus(3);   //退货
        oldBill.setRemark(recoveryBill.getRemark());

        RecoveryGoods recoveryGoods = recoveryGoodsMapper.selectRecoveryGoodsById(oldBill.getGoodsId());
        RecoveryBill newBill = new RecoveryBill();
        newBill.setSellPrice(oldBill.getSellPrice());       //售价
        newBill.setCostPrice(recoveryBill.getCostPrice());  //成本
        newBill.setType(3);     //退单
        newBill.setGoodsId(oldBill.getGoodsId());       //商品编码
        newBill.setGoodsSn(oldBill.getGoodsSn());       //串号
        newBill.setBillName(oldBill.getBillName());     //账单名称
        newBill.setBuyers(oldBill.getBuyers());     //买家
        newBill.setProfit(newBill.getSellPrice().subtract(newBill.getCostPrice())); //利润
        newBill.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        newBill.setCreateId(SecurityUtils.getLoginUser().getUser().getUserId());
        newBill.setCreateTime(new Date());
        newBill.setPaymentType(oldBill.getPaymentType());
        newBill.setRemark(recoveryBill.getRemark());
        newBill.setSellBy(oldBill.getSellBy());
        recoveryBillMapper.insertRecoveryBill(newBill);

        return updateRecoveryBill(oldBill);
    }

    /**
     * 财务账单合计
     * @param bill
     * @return
     */
    @DataScope(deptAlias = "d", userAlias = "u")
    @Override
    public RecoveryData selectRecoveryData(RecoveryBill bill) {
        return recoveryBillMapper.selectRecoveryData(bill);
    }

    /**
     * 条件统计 筛选 获得支付方式
     * @param reqMap  timeType: 开始时间(天：day, 周：week, 月: mouth) hasPayee: 是否根据账户区分
     * @return
     */
    @Override
    public List<Map<String, Object>> conditionSearch(Map<String, Object> reqMap) {
        long oneDay = 1000 * 60 * 60 * 24; //一天时长
        Date startTime = new Date(); //当前时间
        //选择的时间范围
        if("week".equals(reqMap.get("timeType"))) {
            startTime = new Date((startTime.getTime() - oneDay * 6));
        }else if("month".equals(reqMap.get("timeType"))) {
            startTime = new Date(startTime.getTime() - oneDay * 30);
        }
        //财务账单查询条件
        RecoveryBill selBill = new RecoveryBill();
        Map<String , Object> params = new HashMap<>();
        selBill.setType(1);
        params.put("createStartTime", startTime);
        selBill.setParams(params);
        //查询到的数据
        List<RecoveryBill> billList = recoveryBillMapper.selectRecoveryBillList(selBill);
        if(billList.size() == 0) {
            return null;
        }
        //初始化返回的数据
        List<Map<String, Object>> respList = new ArrayList<>();
        Map<String, Object> respMap = new HashMap<>();
        respList.add(respMap);
        //循环财务账单
        for(RecoveryBill bill : billList) {
            //跳过账单类型为3或4的数据
            if(bill.getStatus() == 3 || bill.getStatus() == 4) {
                continue;
            }
            //是否需要分收款账户 进行统计
            if("yes".equals(reqMap.get("hasPayee"))) {
                setMapPaymentTypeByPayee(respList, bill);
            }else {
                //不属于多种支付
                if(bill.getPaymentType() != 4) {
                    setMapPaymentType(respList.get(0), bill.getPaymentType(), bill.getSellPrice());
                }else {
                    JSONArray payJson = JSONArray.parseArray(bill.getPaymentDetail());
                    for(int i = 0; i < payJson.size(); i++) {
                        JSONObject map = JSON.parseObject(payJson.get(i).toString());
                        setMapPaymentType(respList.get(0), map.getInteger("type"), map.getBigDecimal("price"));
                    }
                }
            }
        }
        return respList;
    }

    /**
     *  根据收款账户 统计数据
     * @param list 统计数据列表
     * @param bill 财务账单
     */
    public void setMapPaymentTypeByPayee(List<Map<String, Object>> list, RecoveryBill bill) {
        boolean bool = true;
        if(bill.getPayee() == null) {
            setMapPaymentType(list.get(0), bill.getType(), bill.getSellPrice());
            return;
        }
        for(Map<String, Object> map : list) {
            //并且存在 该支付人map
            if(bill.getPayee().equals(map.get("payee"))) {
                bool = false;
                //不属于多种支付
                if(bill.getPaymentType() != 4) {
                    setMapPaymentType(map, bill.getPaymentType(), bill.getSellPrice());
                }else {
                    setPaymentDetail(list, bill.getPaymentDetail());
                }
                break;
            }
        }
        if(bool) {
            if(bill.getPaymentType() == 4) {
                setPaymentDetail(list, bill.getPaymentDetail());
            }else {
                Map<String, Object> map1 = new HashMap<>();
                map1.put("payee",bill.getPayee());
                setMapPaymentType(map1, bill.getPaymentType(), bill.getSellPrice());
                list.add(map1);
            }

        }
    }

    public void setPaymentDetail(List<Map<String, Object>> mapList, String paymentDetail) {
        JSONArray payJson = JSONArray.parseArray(paymentDetail);
        for(int i = 0; i < payJson.size(); i++) {
            JSONObject mapJson = JSON.parseObject(payJson.get(i).toString());
            if(mapJson.get("payee") == null || "".equals(mapJson.get("payee")) || "null".equals(mapJson.get("payee"))) {
                setMapPaymentType(mapList.get(0), mapJson.getInteger("type"), mapJson.getBigDecimal("price"));
                continue;
            }
            boolean bool = true;
            for(Map<String, Object> map : mapList) {
                if(mapJson.get("payee").equals(map.get("payee"))) {
                    setMapPaymentType(map, mapJson.getInteger("type"), mapJson.getBigDecimal("price"));
                    bool = false;
                    break;
                }
            }
            if(bool) {
                Map<String, Object> map1 = new HashMap<>();
                map1.put("payee", mapJson.get("payee"));
                setMapPaymentType(map1, mapJson.getInteger("type"), mapJson.getBigDecimal("price"));
                mapList.add(map1);
            }
        }
    }

    /**
     * 根据支付方式统计数据类型
     * @param map 统计的数据
     * @param type 支付方式
     * @param price 金额
     */
    public void setMapPaymentType(Map<String, Object> map, Integer type, BigDecimal price) {
        switch (type) {
            case 1:
                map.merge("zhb", price, (a, b) -> ((BigDecimal) b).add((BigDecimal) a));break;
            case 2:
                map.merge("wx", price, (a, b) -> ((BigDecimal) b).add((BigDecimal) a));break;
            case 3:
                map.merge("xj", price, (a, b) -> ((BigDecimal) b).add((BigDecimal) a));break;
            case 5:
                map.merge("dk", price, (a, b) -> ((BigDecimal) b).add((BigDecimal) a));break;
        }
    }

    @Override
    public int updateRecoveryBillByList(Long[] ids) {
        List<RecoveryBill> list = new ArrayList<>();
        Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
        String name = SecurityUtils.getLoginUser().getUser().getNickName();
        for(Long id : ids) {
            RecoveryBill bill = new RecoveryBill();
            bill.setUpdateBy(name);
            bill.setUpdateId(userId);
            bill.setBillId(id);
            list.add(bill);
        }
        return recoveryBillMapper.updateRecoveryBillByList(list);
    }
}
